package sharetime.test.web.controllers;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockHttpServletRequest;

import sharetime.core.EntityObject;
import sharetime.test.BaseSpringContextTestSupport;
import sharetime.util.DateUtils;

/**
 * 
 * @author zhangyf
 *
 */
@SuppressWarnings("unchecked")
public class BaseControllerTestCase extends BaseSpringContextTestSupport {
	
	protected transient final Logger logger = LoggerFactory
			.getLogger(BaseControllerTestCase.class);

	/**
	 * Convenience methods to make tests simpler
	 * 
	 * @return a MockHttpServletRequest with a POST to the specified URL
	 * @param url
	 *            the URL to post to
	 */
	public MockHttpServletRequest newPost(String url) {
		return new MockHttpServletRequest("POST", url);
	}

	public MockHttpServletRequest newGet(String url) {
		return new MockHttpServletRequest("GET", url);
	}
	
	public void objectToRequestParameters(Object o,
			MockHttpServletRequest request, String prefix) throws Exception {
		Class clazz = o.getClass();
		Field[] fields = getDeclaredFields(clazz);
		AccessibleObject.setAccessible(fields, true);

		for (Field f : fields) {
			Object field = (f.get(o));
			if (field != null) {
				if (field instanceof EntityObject) {
					// Fix for http://issues.appfuse.org/browse/APF-429
					if (prefix != null) {
						objectToRequestParameters(field, request, prefix + "."
								+ f.getName());
					} else {
						objectToRequestParameters(field, request, f.getName());
					}
				} else if (!(field instanceof List) && !(field instanceof Set)) {
					String paramName = f.getName();

					if (prefix != null) {
						paramName = prefix + "." + paramName;
					}

					String paramValue = String.valueOf(f.get(o));

					// handle Dates
					if (field instanceof Date) {
						paramValue = DateUtils.convertDateToString((Date) f
								.get(o));
						if ("null".equals(paramValue))
							paramValue = "";
					}

					request.addParameter(paramName, paramValue);
				}
			}
		}
	}

	private Field[] getDeclaredFields(Class clazz) {
		Field[] f = new Field[0];
		Class superClazz = clazz.getSuperclass();
		Collection<Field> rval = new ArrayList<Field>();

		if (superClazz != null) {
			rval.addAll(Arrays.asList(getDeclaredFields(superClazz)));
		}

		rval.addAll(Arrays.asList(clazz.getDeclaredFields()));
		return rval.toArray(f);
	}
}
